home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / SML⁄NJ 93+ / Documentation / examples / textbooks / working / Modules.ML < prev    next >
Encoding:
Text File  |  1995-12-30  |  8.5 KB  |  343 lines  |  [TEXT/R*ch]

  1. (**** ML Programs from the book
  2.  
  3.   ML for the Working Programmer
  4.   by Lawrence C. Paulson, Computer Laboratory, University of Cambridge.
  5.   (Cambridge University Press, 1991)
  6.  
  7. Copyright (C) 1991 by Cambridge University Press.
  8. Permission to copy without fee is granted provided that this copyright
  9. notice and the DISCLAIMER OF WARRANTY are included in any copy.
  10.  
  11. DISCLAIMER OF WARRANTY.  These programs are provided `as is' without
  12. warranty of any kind.  We make no warranties, express or implied, that the
  13. programs are free of error, or are consistent with any particular standard
  14. of merchantability, or that they will meet your requirements for any
  15. particular application.  They should not be relied upon for solving a
  16. problem whose incorrect solution could result in injury to a person or loss
  17. of property.  If you do use the programs or functions in such a manner, it
  18. is at your own risk.  The author and publisher disclaim all liability for
  19. direct, incidental or consequential damages resulting from your use of
  20. these programs or functions.
  21. ****)
  22.  
  23.  
  24. (**** Chapter 7.  MODULES ****)
  25.  
  26. (*** Queues represented by (heads, reversed tails).  See Burton (1982). ***)
  27.  
  28. signature QUEUE = 
  29.   sig
  30.   type 'a T            (*type of queues*)
  31.   exception E            (*for errors in hd, deq*)
  32.   val empty: 'a T        (*the empty queue*)
  33.   val enq: 'a T * 'a -> 'a T    (*add to end*)
  34.   val null: 'a T -> bool    (*test for empty queue*)
  35.   val hd: 'a T -> 'a        (*return front element*)
  36.   val deq: 'a T -> 'a T        (*remove element from front*)
  37.   end;
  38.  
  39.  
  40. structure Queue : QUEUE = 
  41.   struct
  42.   datatype 'a T = Queue of ('a list * 'a list);
  43.   exception E;
  44.  
  45.   val empty = Queue([],[]);
  46.  
  47.   fun norm (Queue([],tails)) = Queue(rev tails, [])
  48.     | norm q = q;
  49.  
  50.   fun enq(Queue(heads,tails), x) = norm(Queue(heads, x::tails));
  51.  
  52.   fun null(Queue([],[])) = true
  53.     | null _ = false;
  54.  
  55.   fun hd(Queue(x::_,_)) = x
  56.     | hd(Queue([],_)) = raise E;
  57.  
  58.   fun deq(Queue(x::heads,tails)) = norm(Queue(heads,tails))
  59.     | deq(Queue([],_)) = raise E;
  60.   end;
  61.  
  62.  
  63. (**** Binary trees as a general-purpose type ***)
  64.  
  65. signature TREE = 
  66.   sig
  67.   datatype 'a T = Lf  |  Br of 'a * 'a T * 'a T
  68.   val count: 'a T -> int
  69.   val depth: 'a T -> int
  70.   val reflect: 'a T -> 'a T
  71.   end;
  72.  
  73.  
  74. functor TreeFUN () : TREE = 
  75.   struct
  76.   datatype 'a T = Lf
  77.         | Br of 'a * 'a T * 'a T;
  78.  
  79.   fun count Lf = 0
  80.     | count (Br(v,t1,t2)) = 1 + count t1 + count t2;
  81.  
  82.   (*book version refers to this as a free identifier*)
  83.   fun maxl[m] : int = m
  84.     | maxl(m::n::ns) = if m>n  then  maxl(m::ns)  else  maxl(n::ns);
  85.  
  86.   fun depth Lf = 0
  87.     | depth (Br(v,t1,t2)) = 1 + maxl[depth t1, depth t2];
  88.  
  89.   fun reflect Lf = Lf
  90.     | reflect (Br(v,t1,t2)) = Br(v, reflect t2, reflect t1);
  91.   end;
  92.  
  93.  
  94. (*** Concrete array operations ***)
  95.  
  96. nonfix sub;  (*required for Standard ML of New Jersey*)
  97.  
  98. signature ARRAYOPS = 
  99.   sig
  100.   structure Tree: TREE
  101.   exception E                (*errors in operations*)
  102.   val sub:    'a Tree.T * int -> 'a
  103.   val update: 'a Tree.T * int * 'a -> 'a Tree.T
  104.   val hirem:  'a Tree.T * int -> 'a Tree.T
  105.   end;
  106.  
  107.  
  108. functor ArrayOpsFUN (structure Tree: TREE) : ARRAYOPS = 
  109.   struct
  110.   structure Tree = Tree;
  111.   exception E;
  112.  
  113.   local open Tree  
  114.   in
  115.     fun sub (Lf, _) = raise E
  116.       | sub (Br(v,t1,t2), k) =
  117.         if k=1 then v
  118.       else if k mod 2 = 0 
  119.          then sub (t1, k div 2)
  120.          else sub (t2, k div 2);
  121.  
  122.     fun update (Lf, k, w) = 
  123.       if k = 1 then Br (w, Lf, Lf)
  124.       else  raise E
  125.       | update (Br(v,t1,t2), k, w) =
  126.       if k = 1 then Br (w, t1, t2)
  127.       else if k mod 2 = 0 
  128.            then Br (v,  update(t1, k div 2, w),  t2)
  129.            else Br (v,  t1,  update(t2, k div 2, w));
  130.  
  131.     fun hirem (Lf, n) = raise E
  132.       | hirem (Br(v,t1,t2), n) =
  133.       if n = 1 then Lf
  134.       else if n mod 2 = 0 
  135.            then Br (v,  hirem(t1, n div 2),  t2)
  136.            else Br (v,  t1,  hirem(t2, n div 2));
  137.   end
  138.   end;
  139.  
  140.  
  141. (*** Functional arrays as abstract type ***)
  142.  
  143. signature ARRAY = 
  144.   sig
  145.   type 'a T
  146.   exception Sub and Update and Hirem
  147.   val empty:  'a T
  148.   val sub:    'a T * int -> 'a
  149.   val update: 'a T * int * 'a -> 'a T
  150.   val hiext:  'a T * 'a -> 'a T
  151.   val hirem:  'a T -> 'a T
  152.   end;
  153.  
  154.  
  155. functor ArrayFUN (structure ArrayOps: ARRAYOPS) : ARRAY = 
  156.   struct
  157.   datatype 'a T = Array of 'a ArrayOps.Tree.T * int;
  158.   exception Sub and Update and Hirem;
  159.  
  160.   val empty = Array(ArrayOps.Tree.Lf, 0);
  161.  
  162.   fun sub (Array(t,n), k) = 
  163.       if 1<=k andalso k<=n 
  164.       then ArrayOps.sub(t,k)
  165.       else raise Sub;
  166.  
  167.   fun update (Array(t,n), k, w) = 
  168.       if 1<=k andalso k<=n 
  169.       then Array(ArrayOps.update(t,k,w), n)
  170.       else raise Update;
  171.  
  172.   fun hiext (Array(t,n), w) = Array(ArrayOps.update(t,n+1,w), n+1);
  173.  
  174.   fun hirem(Array(t,n)) = 
  175.       if n>0 then Array(ArrayOps.hirem(t,n) , n-1)
  176.       else raise Hirem;
  177.   end;
  178.  
  179.  
  180. (**** FUNCTORS ****)
  181.  
  182. (*** Linearly ordered types ***)
  183.  
  184. signature ORDER = 
  185.   sig
  186.   type T
  187.   val less: T*T -> bool
  188.   end;
  189.  
  190.  
  191. (*** Tables as Binary search trees ***)
  192.  
  193. signature TABLE = 
  194.   sig
  195.   type key                (*type of keys*)
  196.   type 'a T                (*type of tables*)
  197.   exception Lookup            (*errors in lookup*)
  198.   val empty: 'a T            (*the empty table*)
  199.   val lookup: 'a T * key -> 'a
  200.   val update: 'a T * key * 'a -> 'a T
  201.   end;
  202.  
  203. functor TableFUN (structure Order: ORDER and Tree: TREE) : TABLE = 
  204.   struct
  205.   type key = Order.T;
  206.   type 'a T = (key * 'a) Tree.T;
  207.   exception Lookup;
  208.  
  209.   local open Tree
  210.   in
  211.     val empty = Lf;
  212.  
  213.     fun lookup (Br ((a,x),t1,t2), b) =
  214.       if      Order.less(b,a) then  lookup(t1, b)
  215.       else if Order.less(a,b) then  lookup(t2, b)
  216.       else x
  217.       | lookup (Lf, b) = raise Lookup;
  218.  
  219.     fun update (Lf, b, y) = Br((b,y), Lf, Lf)
  220.       | update (Br((a,x),t1,t2), b, y) =
  221.       if Order.less(b,a) 
  222.       then  Br ((a,x),  update(t1,b,y),  t2)
  223.       else if Order.less(a,b) 
  224.       then  Br ((a,x),  t1,  update(t2,b,y))
  225.       else (*a=b*) Br ((a,y),t1,t2);
  226.   end
  227.   end;
  228.  
  229.  
  230. (*** Priority queues ***)
  231.  
  232. signature PQUEUE = 
  233.   sig
  234.   structure Order: ORDER    (*ordering for elements*)
  235.   type T            (*type of priority queues*)
  236.   exception E            (*for errors in hd, deq*)
  237.   val empty: T            (*the empty priority queue*)
  238.   val enq: T * Order.T -> T        (*insert into priority queue*)
  239.   val null: T -> bool        (*test for empty*)
  240.   val hd: T -> Order.T        (*return front element*)
  241.   val deq: T -> T        (*remove element from front*)
  242.   end;
  243.  
  244.  
  245. functor PQueueFUN (structure Order: ORDER 
  246.            and       ArrayOps: ARRAYOPS) : PQUEUE = 
  247.   struct
  248.   structure Order = Order;
  249.   datatype T = PQueue of Order.T ArrayOps.Tree.T * int;
  250.   exception E;
  251.  
  252.   local open ArrayOps.Tree
  253.         infix <<
  254.         fun v<<w = Order.less(v,w)
  255.   in
  256.   fun upheap (Lf, n, w) = Br (w, Lf, Lf)
  257.     | upheap (Br(v,t1,t2), n, w) =  (* assume n>1 *)
  258.     if w<<v then
  259.         if n mod 2 = 0 
  260.         then Br (v,  upheap(t1, n div 2, w),  t2)
  261.         else Br (v,  t1,  upheap(t2, n div 2, w))
  262.     else if n mod 2 = 0 
  263.          then Br (w, upheap(t1, n div 2, v), t2)
  264.          else Br (w, t1, upheap(t2, n div 2, v));
  265.  
  266.   fun downheap (Br(_,t1,t2), w) =
  267.     case t1 of  Lf => Br(w,Lf,Lf)
  268.       | Br(v1,_,_) =>
  269.      (case t2 of
  270.          Lf => if v1<<w then Br(w, t1, Lf)
  271.            else Br(v1, downheap(t1,w), Lf)
  272.        | Br(v2,_,_) =>
  273.            if v1<<v2
  274.            then if v2<<w then Br(w, t1, t2)
  275.                  else Br(v2, t1, downheap(t2,w))
  276.            else if v1<<w then Br(w, t1, t2)
  277.                  else Br(v1, downheap(t1,w), t2) );
  278.  
  279.   val empty = PQueue(Lf,0);
  280.  
  281.   fun enq(PQueue(t,n), w) = PQueue(upheap(t,n+1,w), n+1);
  282.  
  283.   fun null (PQueue(Br _, _)) = false
  284.     | null (PQueue(Lf,   _)) = true;
  285.  
  286.   fun hd (PQueue(Br(w,_,_), n)) = w
  287.     | hd (PQueue(Lf,        _)) = raise E;
  288.  
  289.   (*Remove position n from heap, for n>0. *)
  290.   fun deq (PQueue(t,n)) = 
  291.     if n>1 then PQueue(downheap(ArrayOps.hirem(t,n), 
  292.                     ArrayOps.sub(t,n)), 
  293.                n-1)
  294.     else if n=1 then empty
  295.     else raise E;
  296.   end
  297.   end;
  298.  
  299.  
  300. (** Alternative implementation of Tables -- Illustrates eqtype **)
  301. functor AlistFUN (eqtype key) : TABLE = 
  302.   struct
  303.   type key = key;
  304.   type 'a T = (key * 'a) list;
  305.   exception Lookup;
  306.  
  307.   val empty = [];
  308.  
  309.   fun lookup ([], a) = raise Lookup
  310.     | lookup ((x,y)::pairs, a) =
  311.     if a=x then  y  else  lookup(pairs, a);
  312.  
  313.   fun update (pairs, b, y) = (b,y)::pairs;
  314.   end;
  315.  
  316.  
  317. (******** SHORT DEMONSTRATIONS ********)
  318.  
  319. (** Application of the functors  **)
  320. structure Tree = TreeFUN();
  321. structure ArrayOps = ArrayOpsFUN (structure Tree=Tree);
  322. structure FArray = ArrayFUN (structure ArrayOps=ArrayOps);
  323.  
  324. open FArray;
  325. hiext(empty, "A");
  326. hiext(it,"B");
  327. hiext(it,"C");
  328. val tletters = hiext(it,"D");
  329. val tdag = update(tletters, 4, "dagger");
  330. sub(tletters,4);
  331. sub(tdag,4);
  332. hirem tletters;
  333. hirem it;
  334. empty=empty;    (*STILL admits equality!*)
  335.  
  336. structure StringIntAlist = AlistFUN(type key=string*int);
  337. local open StringIntAlist in 
  338. val atab = update(update(empty, ("Henry", 5), "Good"),
  339.           ("Henry", 8), "Bad")
  340. end;
  341.  
  342.  
  343.